package com.noname.lib_base_java.net.download;

import android.annotation.SuppressLint;
import android.os.Environment;

import com.google.gson.GsonBuilder;
import com.noname.lib_base_java.global.GlobalApplication;
import com.noname.lib_base_java.net.BaseApi;
import com.noname.lib_base_java.net.NetManager;
import com.noname.lib_base_java.util.L;
import com.noname.lib_base_java.util.PathUtil;

import org.reactivestreams.Subscription;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Author: Lmoumou
 * Date: 2019-01-22 11:35
 * 文件名: DownloadManager
 * 描述:
 */
public class DownloadManager implements DownloadProgressListener {

    private DownloadInfo info;
    private ProgressListener progressObserver;
    private File outFile;
    private Subscription subscribe;
    private BaseApi service;
    private long currentRead;
    private Observable<ResponseBody> download;

    private DownloadManager() {
    }

    public static DownloadManager getInstance() {
        return Holder.manager;
    }

    public static class Holder {
        private static DownloadManager manager = new DownloadManager();
    }


    @SuppressLint("CheckResult")
    @Override
    public void progress(long read, long contentLength, final boolean done) {
        if (info.getContentLength() > contentLength) {
            read = read + (info.getContentLength() - contentLength);
        } else {
            info.setContentLength(contentLength);
        }
        info.setReadLength(read);

//        L.e("FileUtil", "progress");

        Observable.just(1).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        if (progressObserver != null) {
                            progressObserver.progressChanged(info.getReadLength(), info.getContentLength(), done);
                        }
                    }
                });
    }

    /**
     * 开始下载
     *
     * @param observer
     * @param info
     */
    public void start(Observer<DownloadInfo> observer, DownloadInfo info) {
        this.info = info;
        if (info == null) {
            info = new DownloadInfo();
        }

        String prentPath = Environment.getExternalStorageDirectory() + File.separator + GlobalApplication.getContext().getPackageName() + File.separator;
        File presentFile = new File(prentPath);
        if (!presentFile.exists()) {
            presentFile.mkdir();
        }
        String prentPath2 = Environment.getExternalStorageDirectory() + File.separator + GlobalApplication.getContext().getPackageName() + File.separator + "Download" + File.separator;
        File presentFile2 = new File(prentPath2);
        if (!presentFile2.exists()) {
            presentFile2.mkdir();
        }
        String sPath = Environment.getExternalStorageDirectory() + File.separator + GlobalApplication.getContext().getPackageName() + File.separator + "Download" + File.separator + String.valueOf(info.getThesaurus_id() + ".zip");
        String infoPath = Environment.getExternalStorageDirectory() + File.separator + GlobalApplication.getContext().getPackageName() + File.separator + "Download" + File.separator + "downloadinfo.txt";
        info.setInfoSavePath(infoPath);
        outFile = new File(sPath);
        info.setSavePath(outFile.getAbsolutePath());
        info.setUrl(PathUtil.imgPath(info.getUrl()));
        final DownloadInterceptor interceptor = new DownloadInterceptor(this);
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(8, TimeUnit.SECONDS);
        builder.addInterceptor(interceptor);

        Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create()))
                .baseUrl(NetManager.getInstance().getBaseUrl())
                .build();
        if (service == null)
            service = retrofit.create(BaseApi.class);
//            info.setService(service);
//        } else {
//            service = info.getService();
//        }

        downLoad(observer);
    }

    /**
     * 开始下载
     *
     * @param observer
     */
    private void downLoad(Observer<DownloadInfo> observer) {
        long start = 0;
        File file = new File(info.getSavePath());
        if (file.exists()) {
            start = file.length();
        }

        L.e("ppppppp", "start->" + start);

        info.setReadLength(start);

        if (start != 0 && info.getContentLength() == file.length()) {
            if (progressObserver != null) {
                progressObserver.onAreadyDownload(info);
            }
        } else {
            final long finalStart = start;

            download = service.download("bytes=" + start + "-", info.getUrl());

            /*指定线程*/
            download.subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .retryWhen(new RetryWhenNetworkException())
                    /* 读取下载写入文件，并把ResponseBody转成DownInfo */
                    .map(new Function<ResponseBody, DownloadInfo>() {
                        @Override
                        public DownloadInfo apply(ResponseBody responseBody) throws Exception {
                            try {
                                //下载信息写入文件
                                info.setContentLength(responseBody.contentLength() + finalStart);
                                FileUtil.writeDownloadInfo(info);
                                //zip写入文件
                                FileUtil.writeCache(responseBody, new File(info.getSavePath()), info);
                            } catch (IOException e) {
                                L.e("异常:", e.toString());
                            }
                            return info;
                        }
                    })
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(observer);
        }


    }

    /**
     * 暂停下载
     */
    @SuppressLint("CheckResult")
    public void pause() {

        if (download != null) {
            download.unsubscribeOn(Schedulers.io());
            download.unsubscribeOn(AndroidSchedulers.mainThread());
        }

        if (subscribe != null) {
            subscribe.cancel();
        }

    }

    /**
     * 继续下载
     */
//    public void reStart() {
//        downLoad();
//    }

    /**
     * 进度监听
     */
    public interface ProgressListener {
        void progressChanged(long read, long contentLength, boolean done);

        void onAreadyDownload(DownloadInfo info);
    }

    public void setProgressListener(ProgressListener progressObserver) {
        this.progressObserver = progressObserver;
    }

}
